               PRESERVE8   ; fix the L6306W waring
               AREA |.text|, CODE, READONLY

/**
 * enable all of the interrupts
 * @prototype: void mx_interrupt_enable (void);
 */
mx_interrupt_enable\
               PROC
               EXPORT mx_interrupt_enable
               cpsie i     ; clear PRIMASK (PRIMASK = 0)
               mov pc, lr
               ENDP

/**
 * disable all of the interrupts
 * @prototype: void mx_interrupt_disable (void);
 */
mx_interrupt_disable\
               PROC
               EXPORT mx_interrupt_disable
               cpsid i     ; set PRIMASK (PRIMASK = 1)
               mov pc, lr
               ENDP

/* recover the interrupt state that before called mx_interrupt_disable */
mx_interrupt_enable_nest\
               PROC
               EXPORT mx_interrupt_enable_nest
               msr PRIMASK, r0
               mov pc, lr
               ENDP

/* disable all of the interrupts and return the interrupt state before closing the interrupt */
mx_interrupt_disable_nest\
               PROC
               EXPORT mx_interrupt_disable_nest
               mrs r0, PRIMASK
               cpsid i     ; set PRIMASK (PRIMASK = 1)
               mov pc, lr
               ENDP

/**
 * synchronous exception
 * @prototype: void vector_exception (void);
 * FIXME: not implement the floating-point mode
 */
vector_exception\
               PROC
               EXPORT vector_exception
               b .
               ENDP

/**
 * IRQ handler
 * @prototype: void vector_irq (void);
 * FIXME: not implement the floating-point mode
 */
vector_irq     PROC
               EXPORT vector_irq
               IMPORT mx_interrupt_enter
               IMPORT mx_interrupt_leave
               IMPORT mx_interrupt_handle
               /* here can't occur interrupt nesting by set the NVIC (0 bit for pre-emption priority, 4 bits for subpriority) */
               /* save self-definition region to stack, {r0-r3, r12, lr, pc, xpsr} auto save by hardware.
                  if implement the floating-point mode, the `hardware-auto-save region` is different */
               mov r0, sp              ; save the sp top to r0 which is contain `hardware-auto-save region`
               // self-definition region
               push {lr}               ; lr is EXC_RESULT(0xffffffxx), it's use to exit irq
               push {r4}
               push {r5}
               push {r6}
               push {r7}
               push {r8}
               push {r9}
               push {r10}
               push {r11}
               push {r0}               ; sp, for mx_thread_switch_interrupt if it is called
               mrs r0, PRIMASK
               push {r0}
               mrs r0, FAULTMASK
               push {r0}
               mrs r0, BASEPRI
               push {r0}
               mrs r0, CONTROL
               push {r0}
               /* enter interrupt */
               mov r0, sp
               ldr r4, =mx_interrupt_enter
               blx r4
               /* get the IRQ number and call mx_interrupt_handle function */
               mrs r0, ipsr
               ldr r4, =mx_interrupt_handle
               blx r4
               /* leave interrupt */
               ldr r4, =mx_interrupt_leave
               blx r4
               /* restore self-definition region from stack */
               pop {r0}
               msr CONTROL, r0
               pop {r0}
               msr BASEPRI, r0
               pop {r0}
               msr FAULTMASK, r0
               pop {r0}
               msr PRIMASK, r0
               pop {r0}                ; the sp (load to r0) position not use because not call mx_thread_switch_interrupt function
               pop {r11}
               pop {r10}
               pop {r9}
               pop {r8}
               pop {r7}
               pop {r6}
               pop {r5}
               pop {r4}
               pop {pc}                ; pop the EXC_RESULT (in stack) to pc, do exception exit sequence
               ; nop                     ; fix the A1581W waring
               ENDP

               END
